# cython: language_level=3

cimport cython

from .Visitor cimport CythonTransform, TreeVisitor

cdef class ControlBlock:
     cdef public set children
     cdef public set parents
     cdef public set positions
     cdef public list stats
     cdef public dict gen
     cdef public set bounded

     # Big integer bitsets
     cdef public object i_input
     cdef public object i_output
     cdef public object i_gen
     cdef public object i_kill
     cdef public object i_state

     cpdef bint empty(self)
     cpdef detach(self)
     cpdef add_child(self, block)

cdef class ExitBlock(ControlBlock):
     cpdef bint empty(self)

cdef class NameAssignment:
    cdef public bint is_arg
    cdef public bint is_deletion
    cdef public object lhs
    cdef public object rhs
    cdef public object entry
    cdef public object pos
    cdef public set refs
    cdef public object bit
    cdef public object inferred_type

cdef class AssignmentList:
    cdef public object bit
    cdef public object mask
    cdef public list stats

cdef class AssignmentCollector(TreeVisitor):
    cdef list assignments

@cython.final
cdef class ControlFlow:
     cdef public set blocks
     cdef public set entries
     cdef public list loops
     cdef public list exceptions

     cdef public ControlBlock entry_point
     cdef public ExitBlock exit_point
     cdef public ControlBlock block

     cdef public dict assmts

     cpdef newblock(self, ControlBlock parent=*)
     cpdef nextblock(self, ControlBlock parent=*)
     cpdef bint is_tracked(self, entry)
     cpdef bint is_statically_assigned(self, entry)
     cpdef mark_position(self, node)
     cpdef mark_assignment(self, lhs, rhs, entry)
     cpdef mark_argument(self, lhs, rhs, entry)
     cpdef mark_deletion(self, node, entry)
     cpdef mark_reference(self, node, entry)

     @cython.locals(block=ControlBlock, parent=ControlBlock, unreachable=set)
     cpdef normalize(self)

     @cython.locals(bit=object, assmts=AssignmentList,
                    block=ControlBlock)
     cpdef initialize(self)

     @cython.locals(assmts=AssignmentList, assmt=NameAssignment)
     cpdef set map_one(self, istate, entry)

     @cython.locals(block=ControlBlock, parent=ControlBlock)
     cdef reaching_definitions(self)

cdef class Uninitialized:
     pass

cdef class Unknown:
    pass


cdef class MessageCollection:
    cdef set messages


@cython.locals(dirty=bint, block=ControlBlock, parent=ControlBlock,
               assmt=NameAssignment)
cdef check_definitions(ControlFlow flow, dict compiler_directives)

@cython.final
cdef class ControlFlowAnalysis(CythonTransform):
    cdef object gv_ctx
    cdef object constant_folder
    cdef set reductions
    cdef list env_stack
    cdef list stack
    cdef object env
    cdef ControlFlow flow
    cdef object object_expr
    cdef bint in_inplace_assignment

    cpdef mark_assignment(self, lhs, rhs=*)
    cpdef mark_position(self, node)
